PBDS Set
ย - Last update: 2023-07-18

PBDS Set์— ๊ด€ํ•œ ๊ฐ„๋‹จํ•œ ์ •๋ฆฌ. ์•Œ๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ ์ •๋ฆฌ ์•ˆํ•˜๋ฉด ๋‚˜์ค‘์— ๋‹ค์‹œ ๋งจ๋•…์—์„œ ๊ตฌ๊ธ€๋ง ํ•ด์•ผํ•˜๋ฏ€๋กœ ํ•œ๋ฒˆ ์•Œ๊ฒŒ ๋œ ๋‚ด์šฉ ์ •๋ฆฌํ•˜๊ณ  ๊ฐ€๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

PBDS Set?

PBDS๋Š” Policy based data structures์˜ ์•ฝ์ž๋กœ, g++์—์„œ ext/pb_ds ์•„๋ž˜์— ์œ„์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์นญํ•œ๋‹ค. (MSVC์—์„œ๋Š” ์‚ฌ์šฉ์ด ์–ด๋ ค์šธ ๋“ฏ) ๋ณดํ†ต PS์—์„œ ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ์˜์˜ ์ค‘ ํ•˜๋‚˜๋Š” ๊ธฐ์กด STL Set์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” K๋ฒˆ์งธ ํฌ๊ธฐ๊ฐ€ ํฐ(๋˜๋Š” ์ž‘์€) ์›์†Œ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์ผ๋ฐ˜ set์„ ์‚ฌ์šฉํ•˜๋Š” ๋А๋‚Œ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ defineํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค. ๊ธ€ ํ•˜๋‹จ์— ์˜ˆ์‹œ๊ฐ€ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ordered_set์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

์ผ๋ฐ˜ set์—์„œ ์‚ฌ์šฉ๋˜๋Š” method๋ฅผ ์‚ฌ์šฉํ•จ๊ณผ ๋”๋ถˆ์–ด(์‹ฌ์ง€์–ด iterator๋„ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•จ์„ ํ™•์ธํ–ˆ๋‹ค) ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉ๋˜๋Š” method๋Š” find_by_order(k)์™€ order_of_key(key)์ด๋‹ค. ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ, k๋ฒˆ์งธ ์›์†Œ๋ฅผ O(logโกn)O(\log n) ์— ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ฑฐ๋‚˜, key๊ฐ’์„ ์ฃผ์—ˆ์„ ๋•Œ ๊ทธ๊ฒƒ์ด ๋ช‡๋ฒˆ์งธ ์›์†Œ์ธ์ง€๋ฅผ O(logโกn)O(\log n)์— ์•Œ๊ฒŒ ํ•ด์ค€๋‹ค. ์ผ๋ฐ˜ set์—์„œ ๊ฐ™์€ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์œผ๋ ค๋ฉด O(n)O(n)์˜ ์‹œ๊ฐ„๋ณต์žก๋„์˜€๋˜ ๊ฒƒ์„ ๊ฐ์•ˆํ•˜๋ฉด ํฐ ์ฐจ์ด์ด๋‹ค.

ordered_set X;
X.insert(1);
X.insert(2);
X.insert(4);
X.insert(8);
X.insert(16);
cout<<*X.find_by_order(1)<<endl; // 2
cout<<*X.find_by_order(2)<<endl; // 4
cout<<*X.find_by_order(4)<<endl; // 16
cout<<(end(X)==X.find_by_order(6))<<endl; // true
cout<<X.order_of_key(-5)<<endl; // 0
cout<<X.order_of_key(1)<<endl; // 0
cout<<X.order_of_key(3)<<endl; // 2
cout<<X.order_of_key(4)<<endl; // 2
cout<<X.order_of_key(400)<<endl; // 5

PS ์‚ฌ์šฉ ์˜ˆ์‹œ

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
struct Node {
int priority; // ๋†’์„์ˆ˜๋ก ์œ„์ชฝ์—
int id;
bool operator<(const Node& t) const {
if (priority != t.priority) return priority < t.priority;
return id < t.id;
}
bool operator>(const Node& t) const {
return t < *this;
}
};
#define ordered_set tree<Node, null_type, less<Node>, rb_tree_tag,tree_order_statistics_node_update>

์—ฌ๊ธฐ์„œ ์‚ฌ์šฉํ•œ ๊ตฌํ˜„์ฒด๋Š” rb_tree์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ์ข€ ์ฐพ์•„๋ณด๋‹ˆ ์ด ๊ตฌํ˜„์ฒด๋ฅผ splay_tree ๋“ฑ์œผ๋กœ๋„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š”๊ฑฐ ๊ฐ™๋‹ค. ์‹œ๊ฐ„ ์ œํ•œ์ด ๋นก๋นกํ•˜๋‹ค๋ฉด ์ด๋Ÿฐ ๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ”๊ฟ”๊ฐ€๋ฉด์„œ ํ…Œ์ŠคํŠธํ•ด๋ด๋„ ์ข‹์„ ๋“ฏ.

  • ํ’€์ด ์‚ฌ์šฉ
void solve() {
ordered_set S;
unordered_map<int, ordered_set::point_iterator> M;
int N, CASE; scanf("%d %d", &N, &CASE);
for(int i = 1; i <= N; ++i) {
auto res = S.insert({N - i + 1, i});
auto it = res.first;
M.emplace(i, it);
}
// for(auto& it: S) {
// printf("(%d, %d)\n", it.priority, it.id);
// }
int priority = N + 1;
for(int i = 0; i < CASE; ++i) {
int c; scanf("%d", &c);
auto mit = M.find(c);
auto sit = mit->second;
M.erase(mit);
// ์•„๋ž˜ ๋ถ€๋ถ„์ด ๋ช‡ ๋ฒˆ์งธ ์›์†Œ์ธ์ง€ ๋น ๋ฅด๊ฒŒ ์ฐพ๋Š” ๋ถ€๋ถ„์ด๋‹ค. ์ผ๋ฐ˜ set์—๋Š” ์—†๋Š” method
int cdist = S.order_of_key(*sit); //distance(sit, S.end());
int cid = sit->id;
S.erase(sit);
auto res = S.insert({priority, cid});
auto it = res.first;
priority++;
M.emplace(cid, it);
printf("%d ", N - cdist - 1);
}
printf("\n");
}

์ด ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ ๋”ฑ ์ฝ๊ธฐ๋งŒ ํ•ด๋„ Ordered Set์ด ์‚ฌ์šฉ๋˜๋ฉด ํŽธํ•˜๊ฒŒ ํ’€ ์ˆ˜ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ ๋‹ค. ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ๊ธฐ๋ฒ•์œผ๋กœ ์›์†Œ๋ฅผ ๋„ฃ๊ณ  ๋นผ๋‹ค๊ฐ€, (K - 1) / 2 ๋ฒˆ์งธ ์›์†Œ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๊ธฐ๋งŒ ํ•˜๋ฉด ์‰ฝ๊ฒŒ ๊ตฌํ˜„์ด ๋˜๋Š” ๋ฌธ์ œ์ด๋‹ค.

  • ์„ ์–ธ๋ถ€
#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
struct Node {
int degree;
int id;
bool operator<(const Node& t) const {
if (degree != t.degree) return degree < t.degree;
return id < t.id;
}
bool operator>(const Node& t) const {
return t < *this;
}
};
#define ordered_set tree<Node, null_type, less<Node>, rb_tree_tag,tree_order_statistics_node_update>
ordered_set v;

id์˜ ๊ฒฝ์šฐ ์ค‘๋ณต๊ฐ’ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์กด์žฌํ•œ๋‹ค. (์ค‘๋ณต๋˜์„œ ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€)

  • ๋กœ์ง ์ž‘์„ฑ
int A[250000];
int main() {
int N, K; scanf("%d %d", &N, &K);
for(int i = 0; i < N; ++i) scanf("%d", &A[i]);
int cur = 0;
for(int i = 0; i < K; ++i) {
v.insert({A[i], i});
}
int mid = (K - 1) / 2;
long long ans = v.find_by_order(mid)->degree;
int l = 0;
int r = K;
for(; r < N; ++r, ++l) {
v.insert({A[r], r});
v.erase(v.find({A[l], l}));
ans += v.find_by_order(mid)->degree;
}
printf("%lld\n", ans);
return 0;
}
๐Ÿท๏ธ ์ฃผ์ œ ๋ชฉ๋ก: